package com.study.thirdpartyeventconsumer.config.mybatis;

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.study.thirdpartyeventconsumer.constant.BaseEnum;
import jakarta.annotation.PostConstruct;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Configuration
@ConditionalOnClass({SqlSessionFactory.class, MybatisSqlSessionFactoryBean.class})
public class EnumTypeHandlerAutoConfiguration {

    @Value("${mybatis-plus.enum.scan-packages:com.yourcompany}")
    private String scanPackages;

    private final SqlSessionFactory sqlSessionFactory;

    public EnumTypeHandlerAutoConfiguration(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    @PostConstruct
    public void registerEnumTypeHandlers() {
        TypeHandlerRegistry typeHandlerRegistry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();

        try {
            List<Class<?>> enumClasses = scanEnumClasses();

            for (Class<?> enumClass : enumClasses) {
                if (BaseEnum.class.isAssignableFrom(enumClass)) {
                    // 实现了BaseEnum接口的枚举使用自定义TypeHandler
                    registerBaseEnumTypeHandler(typeHandlerRegistry, enumClass);
                } else {
                    // 没有实现BaseEnum接口的枚举使用默认处理器（MyBatis-Plus的EnumOrdinalTypeHandler或EnumTypeHandler）
                    // MyBatis-Plus默认会处理，这里可以不做特殊处理
                    System.out.println("Enum " + enumClass.getSimpleName() + " will use default type handler");
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to register enum type handlers", e);
        }
    }

    @SuppressWarnings("unchecked")
    private void registerBaseEnumTypeHandler(TypeHandlerRegistry registry, Class<?> enumClass) {
        try {
            BaseEnumTypeHandler handler = new BaseEnumTypeHandler(enumClass);
            registry.register(enumClass, handler);
            System.out.println("Registered BaseEnumTypeHandler for " + enumClass.getSimpleName());
        } catch (Exception e) {
            System.err.println("Failed to register BaseEnumTypeHandler for " + enumClass.getSimpleName() + ": " + e.getMessage());
        }
    }

    private List<Class<?>> scanEnumClasses() throws IOException {
        List<Class<?>> enumClasses = new ArrayList<>();
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory();

        String[] packages = scanPackages.split(",");
        for (String basePackage : packages) {
            String packagePath = ClassUtils.convertClassNameToResourcePath(basePackage.trim());
            String pattern = "classpath*:" + packagePath + "/**/*.class";

            Resource[] resources = resolver.getResources(pattern);
            for (Resource resource : resources) {
                if (resource.isReadable()) {
                    MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
                    String className = metadataReader.getClassMetadata().getClassName();

                    try {
                        Class<?> clazz = Class.forName(className);
                        if (clazz.isEnum()) {
                            enumClasses.add(clazz);
                        }
                    } catch (ClassNotFoundException | NoClassDefFoundError e) {
                        // 忽略无法加载的类
                        System.out.println("Could not load class: " + className);
                    }
                }
            }
        }

        return enumClasses;
    }
}